package Code

import (
	"context"

	"github.com/gogf/gf/v2/errors/gcode"
	"github.com/gogf/gf/v2/errors/gerror"

	"Yoj/api/Code/FileSubmit"

	v12 "Yoj/internal/controller/YJudger"
	"Yoj/internal/dao"
	"Yoj/internal/model/do"
	"io"

	"github.com/gogf/gf/v2/os/glog"
	"github.com/gogf/gf/v2/os/gtime"
)

// 检查提交文件;
func CheckFileSubmit(ctx context.Context, req *FileSubmit.CodeFileSubmitReq) error {
	if req.File == nil {
		return gerror.NewCode(gcode.CodeInvalidParameter, "文件不能为空")
	}
	if req.File.Size > 1024*1024*10 {
		return gerror.NewCode(gcode.CodeInvalidParameter, "文件大小不能超过10M")
	}
	return nil
}

// 获取文件内容;
func GetFileContent(ctx context.Context, req *FileSubmit.CodeFileSubmitReq) (*string, error) {
	// 读取文件内容;
	file, err := req.File.Open()
	if err != nil {
		glog.Error(ctx, err)
		return nil, gerror.NewCode(gcode.CodeInternalError, "文件读取失败")
	}
	defer file.Close()

	content, err := io.ReadAll(file)
	if err != nil {
		glog.Error(ctx, err)
		return nil, gerror.NewCode(gcode.CodeInternalError, "文件读取失败")
	}

	res := string(content)
	return &res, nil
}

// 写入数据库;
func FileCodeWriteToDatabase(ctx context.Context, req *FileSubmit.CodeFileSubmitReq, content *string) (int64, error) {
	result, err := dao.Submit.Ctx(ctx).Insert(do.Submit{
		SubmitUser: req.Qid,
		SubmitAt:   gtime.Now(),
		Code:       content,
		ProblemId:  req.Problem,
	})
	if err != nil {
		glog.Error(ctx, err)
		glog.Print(ctx, err)
		return 0, gerror.NewCode(gcode.CodeInternalError, "数据库写入失败")
	}
	id, err := result.LastInsertId()
	if err != nil {
		glog.Error(ctx, err)
		return 0, gerror.NewCode(gcode.CodeInternalError, "数据库写入失败")
	}
	return id, nil
}

func (c *ControllerFileSubmit) CodeFileSubmit(ctx context.Context, req *FileSubmit.CodeFileSubmitReq) (res *FileSubmit.CodeFileSubmitRes, err error) {
	if v12.CheckLanguage(req.Language) == false {
		return nil, gerror.NewCode(gcode.CodeInvalidParameter, "不支持的语言")
	}
	if req.Name != ctx.Value("username").(string) {
		glog.Infof(ctx, "req.Name: %s, ctx.Value(username): %s", req.Name, ctx.Value("username").(string))
		return nil, gerror.NewCode(gcode.CodeInvalidParameter, "用户名校验失败")
	}
	if req.Qid != ctx.Value("qid").(string) {
		glog.Infof(ctx, "req.Qid: %s, ctx.Value(qid): %s", req.Qid, ctx.Value("qid").(string))
		return nil, gerror.NewCode(gcode.CodeInvalidParameter, "Qid校验失败")
	}

	// 检查提交文件;
	if err := CheckFileSubmit(ctx, req); err != nil {
		return nil, err
	}

	// 读取文件内容;
	content, err := GetFileContent(ctx, req)
	if err != nil {
		return nil, err
	}

	// 写入数据库;
	var submitId int64
	if submitId, err = FileCodeWriteToDatabase(ctx, req, content); err != nil {
		return nil, err
	}

	// TODO: 通知评测机;

	// 返回提交id;
	res = &FileSubmit.CodeFileSubmitRes{
		Submitid: submitId,
	}
	return
}
